package server

import (
	"golang.org/x/net/websocket"
	"fmt"
	"io"
	"log"
)

const channelBufSize  = 100

var maxInt int = 0

type Client struct {
	id int
	ws *websocket.Conn
	server *Server
	ch chan *Message
	doneCh chan bool
}

func NewClient(ws *websocket.Conn, server *Server) *Client{
	if ws == nil{
		panic("ws cannot be nil")
	}
	if server == nil {
		panic("server cannot be nil")
	}
	maxInt ++
	ch := make(chan *Message, channelBufSize)
	doneCh := make(chan bool)
	return &Client{maxInt, ws, server, ch, doneCh}
}

func (this *Client) Conn() *websocket.Conn {
	return this.ws
}
func (this *Client) Write(msg *Message) {
	select {
	case this.ch <- msg:
	default:
		this.server.Del(this)
		err := fmt.Errorf("client %d is disconnected.", this.id)
		this.server.Err(err)
		
	}
}
func (this *Client) Done() {
	this.doneCh <- true
}
func (this *Client) Listen() {
	go this.listenWrite()
	this.listenRead()
}
// Listen write request via chanel
func (this *Client) listenWrite() {
	log.Println("Listening write to client")
	for {
		select {
		// send message to the client
		case msg := <-this.ch:
			log.Println("Send:", msg)
			websocket.JSON.Send(this.ws, msg)

		// receive done request
		case <-this.doneCh:
			this.server.Del(this)
			this.doneCh <- true // for listenRead method
			return
		}
	}
}

// Listen read request via chanel
func (this *Client) listenRead() {
	log.Println("Listening read from client")
	for {
		select {

		// receive done request
		case <-this.doneCh:
			this.server.Del(this)
			this.doneCh <- true // for listenWrite method
			return

		// 从连接中读取数据
		default:
			var msg Message
			err := websocket.JSON.Receive(this.ws, &msg)
			if err == io.EOF {
				this.doneCh <- true
			} else if err != nil {
				this.server.Err(err)
			} else {
				this.server.SendAll(&msg)
			}
		}
	}
}
